package org.sction.action.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;

import org.apache.log4j.Logger;
import org.sction.action.annotation.Action;
import org.sction.action.annotation.Controller;
import org.sction.action.annotation.MethodParam;
import org.sction.action.annotation.Parameter;
import org.sction.action.core.BaseAction;
import org.sction.security.encoding.XXTEA;
import org.sction.util.FileUtils;


/**
 * @author 作者 : sorc
 * @version 创建时间：2012-3-15 上午9:47:24
 * 
 *          类说明
 */
@Controller("system/run")
public class Run extends BaseAction {

	private static Logger log = Logger.getLogger(Run.class);
	@Parameter
	public String clazz = null;
	@Parameter
	public String method = null;
	@Parameter
	public String params = null;

	@Parameter
	public int rownum = 0;

	public static String jad = null;

	@Action
	public String em(@MethodParam("data") String data,
			@MethodParam("key") String key) {
		try {
			return XXTEA.encrypt(data, key);
		} catch (UnsupportedEncodingException e) {
			return "";
		}
	}

	@Action
	public String dm(@MethodParam("data") String data,
			@MethodParam("key") String key) {
		try {
			return XXTEA.decrypt(data, key);
		} catch (Exception e) {
			return "";
		}
	}

	@Action
	public String classInfo() {
		String info = null;
		Class<?> klass = null;
		int cols = 1;
		if (clazz == null) {
			info = "参数clazz不允许空";
			log.error(info);
		} else {
			try {
				info = "";
				info += "<html>\n<head>\n";
				info += "<html>\n<head>\n";
				info += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n";
				info += "<script type=\"text/javascript\">\n";
				try {
					info += FileUtils.read(this.getClass().getResource(
							"/js/shCore.js"))
							+ "\n";
				} catch (IOException e3) {
					e3.printStackTrace();
				}
				try {
					info += FileUtils.read(this.getClass().getResource(
							"/js/shBrushJava.js"))
							+ "\n";
				} catch (IOException e2) {
					e2.printStackTrace();
				}
				info += "</script>\n";
				info += "<style type=\"text/css\">\n";
				try {
					info += FileUtils.read(this.getClass().getResource(
							"/js/shCoreEclipse.css"))
							+ "\n";
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				info += "</style>\n";
				info += "<script type=\"text/javascript\">SyntaxHighlighter.all();</script>\n";
				info += "</head>\n<body>\n<table>\n";
				klass = Class.forName(clazz);
				info += "<tr><td align=\"center\" nowrap=\"nowrap\" colspan=\""
						+ (cols * 2) + "\">" + klass.getCanonicalName();
				String classType = "";
				if (klass.isAnnotation()) {
					classType += "注解;";
				}
				if (klass.isArray()) {
					classType += "数组;";
				}
				if (klass.isEnum()) {
					classType += "枚举;";
				}
				if (klass.isInterface()) {
					classType += "接口;";
				}
				if (klass.isAnonymousClass()) {
					classType += "匿名类;";
				}
				if (klass.isLocalClass()) {
					classType += "本地类;";
				}
				if (klass.isMemberClass()) {
					if (klass.getDeclaringClass() != null) {
						classType += toClassInfoLink(klass.getDeclaringClass())
								+ "的";
					}
					classType += "成员类;";
				}
				if (klass.isPrimitive()) {
					classType += "基本类;";
				}
				if (klass.isSynthetic()) {
					classType += "复合类;";
				}
				if (!classType.equals("")) {
					info += "&nbsp;&nbsp;&nbsp;&nbsp;["
							+ classType.substring(0, classType.length() - 1)
							+ "]";
				}
				info += "</td></tr>";
				info += "<tr><td colspan=\"" + (cols * 2)
						+ "\"><hr/></td></tr>";

				Class<?> superClass = klass.getSuperclass();
				if (superClass != null) {
					info += "<tr><td align=\"right\" colspan=\"" + cols
							+ "\">父类：</td><td colspan=\"" + cols + "\">"
							+ toClassInfoLink(superClass) + "</td></tr>";
				}
				Class<?>[] interfaces = klass.getInterfaces();
				if (interfaces != null && interfaces.length > 0) {
					info += "<tr><td align=\"right\" colspan=\"" + cols
							+ "\" rowspan=\"" + interfaces.length
							+ "\">接口：</td>";
					for (Class<?> interface1 : interfaces) {
						info += "<td colspan=\"" + cols + "\">"
								+ toClassInfoLink(interface1) + "</td></tr>";
					}
				}
				// Type[] interfacesTypes = klass.getGenericInterfaces();
				// if (interfacesTypes != null && interfacesTypes.length > 0) {
				// info += "<tr><td colspan=\"" + cols + "\" rowspan=\""
				// + interfaces.length + "\">接口x：</td>";
				// for (Type type : interfacesTypes) {
				// info += "<td colspan=\"" + cols + "\">"
				// + type.toString() + "</td></tr>";
				// }
				// }
				Annotation[] annotations = klass.getAnnotations();
				if (annotations != null && annotations.length > 0) {
					info += "<tr><td align=\"right\" colspan=\"" + cols
							+ "\" rowspan=\"" + annotations.length
							+ "\">注解：</td>";
					for (Annotation annotation : annotations) {
						info += "<td colspan=\"" + cols + "\">"

						+ toClassInfoLink(annotation.annotationType())
								+ "</td></tr>";
					}
				}
				Field[] fields = klass.getDeclaredFields();
				if (fields != null && fields.length > 0) {
					info += "<tr><td align=\"right\" colspan=\"" + cols
							+ "\" rowspan=\"" + fields.length + "\">属性：</td>";
					for (Field field : fields) {
						info += "<td colspan=\"" + cols + "\">"
								+ field.toString() + "</td></tr>";
					}
				}
				Constructor<?>[] constructors = klass.getDeclaredConstructors();
				if (constructors != null && constructors.length > 0) {
					info += "<tr><td nowrap=\"nowrap\" colspan=\"" + cols
							+ "\" rowspan=\"" + constructors.length
							+ "\">构造方法：</td>";
					for (Constructor<?> constructor : constructors) {
						info += "<td colspan=\"" + cols + "\">"
								+ constructor.toString() + "</td></tr>";
					}
				}
				Method[] methods = klass.getDeclaredMethods();
				if (methods != null && methods.length > 0) {
					info += "<tr><td align=\"right\" colspan=\"" + cols
							+ "\" rowspan=\"" + methods.length + "\">方法：</td>";
					for (Method method : methods) {
						info += "<td colspan=\"" + cols + "\">"
								+ method.toString() + "</td></tr>";
					}
				}
				if (klass.isEnum()) {
					Object[] types = klass.getEnumConstants();
					if (types != null && types.length > 0) {
						info += "<tr><td align=\"right\" nowrap=\"nowrap\" colspan=\""
								+ cols
								+ "\" rowspan=\""
								+ types.length
								+ "\">枚举成员：</td>";
						for (Object object : types) {
							info += "<td colspan=\"" + cols + "\">"
									+ object.toString() + "</td></tr>";
						}
					}
				}
				if (klass.isInterface()) {
					try {
						List<Class<?>> classes = getAllImplement(klass, false);
						if (classes != null && !classes.isEmpty()) {
							info += "<tr><td align=\"right\" nowrap=\"nowrap\" colspan=\""
									+ cols
									+ "\" rowspan=\""
									+ classes.size()
									+ "\">已知实现类：</td>";
							for (Class<?> class1 : classes) {
								info += "<td colspan=\"" + cols + "\">"
										+ toClassInfoLink(class1)
										+ "</td></tr>";
							}
						}
					} catch (IllegalStateException e) {
						e.printStackTrace();
					} catch (IOException e) {
						e.printStackTrace();
					}

				}
				try {
					List<Class<?>> classes = getAllSubClass(klass, false);
					if (classes != null && !classes.isEmpty()) {
						info += "<tr><td align=\"right\" nowrap=\"nowrap\" colspan=\""
								+ cols
								+ "\" rowspan=\""
								+ classes.size()
								+ "\">已知子类：</td>";
						for (Class<?> class1 : classes) {
							info += "<td colspan=\"" + cols + "\">"
									+ toClassInfoLink(class1) + "</td></tr>";
						}
					}
				} catch (IllegalStateException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}

				Class<?>[] classes = klass.getDeclaredClasses();
				if (classes != null && classes.length > 0) {
					info += "<tr><td align=\"right\" colspan=\"" + cols
							+ "\" rowspan=\"" + classes.length + "\">成员类：</td>";
					for (Class<?> class1 : classes) {
						info += "<td colspan=\"" + cols + "\">"
								+ toClassInfoLink(class1) + "</td></tr>";
					}
				}
				ClassLoader classLoader = klass.getClassLoader();
				if (classLoader != null) {
					info += "<tr><td align=\"right\" colspan=\"" + cols
							+ "\">加载器：</td><td colspan=\"" + cols + "\">"
							+ classLoader.toString()
							+ "&nbsp;&nbsp;:&nbsp;&nbsp;"
							+ toClassInfoLink(classLoader.getClass())
							+ "</td></tr>";
				}
				info += "</table>\n";
				info += "<pre class=\"brush:java;\">\n";
				String pathx = decompile(klass.getName().replaceAll("\\.", "/")
						+ ".class");
				try {
					info += read(pathx) + "\n";
				} catch (IOException e) {
					e.printStackTrace();
				}
				info += "</pre>\n";
				info += "</body>\n<html>";
			} catch (ClassNotFoundException e) {
				info = "没有发现类：" + e.getMessage();
			} finally {
				klass = null;
				clazz = null;
				method = null;
				params = null;
			}
		}
		return info;
	}

	public static String read(String filepath) throws IOException {
		BufferedReader reader = new BufferedReader(new InputStreamReader(
				new FileInputStream(filepath)));
		String line = "";
		String out = "";
		while ((line = reader.readLine()) != null) {
			if (!line.trim().startsWith("//"))
				out += line + "\n";
		}
		reader.close();
		return out;
	}

	/**
	 * http://127.0.0.1:8080/Run!local.do?clazz=com.aide.test.Test
	 */
	@Action
	public void local() {
		String info = null;
		Object obj = null;
		Class<?>[] argTypes = null;
		Object[] args1 = null;
		Class<?> klass = null;
		Method m = null;
		Object clobj = null;
		PrintWriter out = null;
		try {

			if (clazz == null) {
				info = "参数clazz不允许空";
				log.error(info);
			} else {
				if (method == null) {
					method = "main";
					argTypes = new Class[] { java.lang.String[].class };
					if (params != null) {
						args1 = new Object[] { (Object[]) params.split(",") };
					} else {
						args1 = new Object[] { new String[] {} };
					}
				} else if (params != null) {
					args1 = (Object[]) params.split(",");
					if (args1.length == 1) {
						argTypes = new Class[] { java.lang.String.class };
					} else {
						argTypes = new Class[args1.length];
						for (int i = 0; i < argTypes.length; i++) {
							argTypes[i] = java.lang.String.class;
						}
					}
				}

				try {
					klass = Class.forName(clazz);
				} catch (ClassNotFoundException e) {
					info = "没有发现类：" + e.getMessage();
					log.error(info, e);
				}
				try {
					if (klass != null)
						m = klass.getMethod(method, argTypes);
				} catch (SecurityException e) {
					info = "安全异常：" + e.getMessage();
					log.error(info, e);
				} catch (NoSuchMethodException e) {
					info = "没有发现方法：" + e.getMessage();
					log.error(info, e);
				}
				try {
					if (m != null) {
						try {
							obj = m.invoke(null, args1);
						} catch (java.lang.NullPointerException e) {
							try {
								clobj = klass.newInstance();
							} catch (InstantiationException e1) {
								info = "没有无参构造方法：" + e1.getMessage();
								log.error(info, e1);
							}
							if (clobj != null)
								obj = m.invoke(clobj, args1);
						}

					}
				} catch (IllegalArgumentException e) {
					info = "运行方法错误1：" + e.getMessage();
					log.error(info, e);
				} catch (IllegalAccessException e) {
					info = "运行方法错误2：" + e.getMessage();
					log.error(info, e);
				} catch (InvocationTargetException e) {
					info = "运行方法错误3：" + e.getMessage();
					log.error(info, e);
				}
			}
			out = response.getWriter();
			response.setContentType("text/html; charset=utf-8");
			response.setHeader("Cache-Control", "no-cache");
			if (info == null) {
				out.println("执行成功：");
				out.println(obj);
			} else {
				out.println("执行失败：");
				out.println(info);
			}
			out.flush();
			out.close();
			out = null;
		} catch (Exception e) {
			log.error(e);
		} finally {
			if (out != null) {
				out.close();
				out = null;
			}
			info = null;
			obj = null;
			argTypes = null;
			args1 = null;
			klass = null;
			m = null;
			clobj = null;
			clazz = null;
			method = null;
			params = null;
		}

	}

	/**
	 * http://127.0.0.1:8080/Run!remote.do?clazz=127.0.0.1:8080/Test&method=
	 * test2&params=11,222
	 */
	@Action
	public void remote() {
		String info = null;
		Object obj = null;
		Class<?>[] argTypes = null;
		Object[] args1 = null;
		Class<?> klass = null;
		Method m = null;
		Object clobj = null;
		PrintWriter out = null;
		try {

			if (clazz == null) {
				info = "参数clazz不允许空";
				log.error(info);
			} else {
				if (method == null) {
					method = "main";
					argTypes = new Class[] { java.lang.String[].class };
					if (params != null) {
						args1 = new Object[] { (Object[]) params.split(",") };
					} else {
						args1 = new Object[] { new String[] {} };
					}
				} else if (params != null) {
					args1 = (Object[]) params.split(",");
					if (args1.length == 1) {
						argTypes = new Class[] { java.lang.String.class };
					} else {
						argTypes = new Class[args1.length];
						for (int i = 0; i < argTypes.length; i++) {
							argTypes[i] = java.lang.String.class;
						}
					}
				}

				try {
					ClassLoader cl = this.getClass().getClassLoader();
					if (cl == null) {
						log.warn("未找到类加载器，使用自定义的类加载器");
						cl = new org.sction.core.ClassLoader();
					}
					try {
						klass = cl.loadClass(clazz);
					} catch (ClassNotFoundException e) {
						org.sction.core.ClassLoader ccl = new org.sction.core.ClassLoader();
						klass = ccl.loadClass(clazz);
					}

				} catch (ClassNotFoundException e) {
					info = "没有发现类1：" + e.getMessage();
					log.error(info, e);
				}
				try {
					if (klass != null)
						m = klass.getMethod(method, argTypes);
				} catch (SecurityException e) {
					info = "安全异常：" + e.getMessage();
					log.error(info, e);
				} catch (NoSuchMethodException e) {
					info = "没有发现方法：" + e.getMessage();
					log.error(info, e);
				}
				try {
					if (m != null) {
						try {
							obj = m.invoke(null, args1);
						} catch (java.lang.NullPointerException e) {
							try {
								clobj = klass.newInstance();
							} catch (InstantiationException e1) {
								info = "没有无参构造方法：" + e1.getMessage();
								log.error(info, e1);
							}
							if (clobj != null)
								obj = m.invoke(clobj, args1);
						}

					}
				} catch (IllegalArgumentException e) {
					info = "运行方法错误1：" + e.getMessage();
					log.error(info, e);
				} catch (IllegalAccessException e) {
					info = "运行方法错误2：" + e.getMessage();
					log.error(info, e);
				} catch (InvocationTargetException e) {
					info = "运行方法错误3：" + e.getMessage();
					log.error(info, e);
				}
			}
			out = response.getWriter();
			response.setContentType("text/html; charset=utf-8");
			response.setHeader("Cache-Control", "no-cache");
			if (info == null) {
				out.println("执行成功：");
				out.println(obj);
			} else {
				out.println("执行失败：");
				out.println(info);
			}
			out.flush();
			out.close();
			out = null;
		} catch (Exception e) {
			log.error(e);
		} finally {
			if (out != null) {
				out.close();
				out = null;
			}
			info = null;
			obj = null;
			argTypes = null;
			args1 = null;
			klass = null;
			m = null;
			clobj = null;
			clazz = null;
			method = null;
			params = null;
		}

	}

	private String toClassInfoLink(Class<?> clazz) {
		return "<a href=\"/Run!classInfo.do?clazz=" + clazz.getName() + "\">"
				+ clazz.getName() + "</a>";
	}

	/**
	 * 获取接口的所有实现类
	 * 
	 * @param clazz
	 *            接口类
	 * @param samePackage
	 *            是否为同一包路径下
	 * @return
	 * @throws ClassNotFoundException
	 * @throws IOException
	 */
	public static List<Class<?>> getAllImplement(Class<?> clazz,
			boolean samePackage) throws IOException, ClassNotFoundException,
			IllegalStateException {
		// ClassLoader $loader = interfaceClass.getClassLoader();
		ClassLoader $loader = Thread.currentThread().getContextClassLoader();
		/** 获取包名称 */
		String packageName = samePackage ? clazz.getPackage().getName() : "/";
		return findClasses(clazz, $loader, packageName, 1);
	}

	public static List<Class<?>> getAllSubClass(Class<?> clazz,
			boolean samePackage) throws IOException, ClassNotFoundException,
			IllegalStateException {
		// ClassLoader $loader = interfaceClass.getClassLoader();
		ClassLoader $loader = Thread.currentThread().getContextClassLoader();
		/** 获取包名称 */
		String packageName = samePackage ? clazz.getPackage().getName() : "/";
		return findClasses(clazz, $loader, packageName, 2);
	}

	/**
	 * 获取实现接口的实现类文件
	 * 
	 * @param clazz
	 * @param loader
	 * @param packageName
	 * @return
	 * @throws IOException
	 * @throws ClassNotFoundException
	 */
	private static List<Class<?>> findClasses(Class<?> clazz,
			ClassLoader loader, String packageName, int type)
			throws IOException, ClassNotFoundException {

		List<Class<?>> allClasses = new ArrayList<Class<?>>();
		/** 获取包路径 */
		String packagePath = packageName.replace(".", "/");
		if (!packagePath.equals("/")) {
			Enumeration<URL> resources = loader.getResources(packagePath);
			while (resources.hasMoreElements()) {
				URL $url = resources.nextElement();
				allClasses.addAll(findResources(clazz,
						new File($url.getFile()), packageName, type));
			}
		} else {
			String path = loader.getResource("").getPath();
			allClasses.addAll(findResources(clazz, new File(path), packageName,
					type));
		}
		return allClasses;
	}

	/**
	 * 获取文件资源信息
	 * 
	 * @param interfaceClass
	 * @param directory
	 * @param packageName
	 * @return
	 * @throws ClassNotFoundException
	 */
	@SuppressWarnings("unchecked")
	private static List<Class<?>> findResources(Class<?> clazz1,
			File directory, String packageName, int type)
			throws ClassNotFoundException {

		List<Class<?>> $results = new ArrayList<Class<?>>();
		if (!directory.exists())
			return Collections.EMPTY_LIST;
		File[] files = directory.listFiles();
		for (File file : files) {
			if (file.isDirectory()) {
				// 文件夹-->继续遍历
				if (!file.getName().contains(".")) {
					if (!packageName.equals("/")) {
						$results.addAll(findResources(clazz1, file, packageName
								+ "." + file.getName(), type));
					} else {
						$results.addAll(findResources(clazz1, file,
								file.getName(), type));
					}
				}
			} else if (file.getName().endsWith(".class")) {
				Class<?> clazz = null;
				if (!packageName.equals("/")) {
					clazz = Class.forName(packageName
							+ "."
							+ file.getName().substring(0,
									file.getName().length() - 6));
				} else {
					clazz = Class.forName(file.getName().substring(0,
							file.getName().length() - 6));
				}

				if (clazz1.isAssignableFrom(clazz) && !clazz1.equals(clazz)) {
					// 取子类
					if (type == 2) {
						if (clazz1.isInterface() && clazz.isInterface()) {// 接口的子类
							$results.add(clazz);
						} else if (!clazz1.isInterface()
								&& !clazz.isInterface()) {// 类的子类
							Class<?> superClass = clazz.getSuperclass();
							if (clazz1.equals(superClass)) {
								$results.add(clazz);
							}
						}
					}
					// 接口实现
					if (type == 1) {
						if (clazz1.isInterface() && !clazz.isInterface()) {
							$results.add(clazz);
						}
					}
				}
			}
		}
		return $results;
	}

	public String decompile(String src) {
		String path = this.getClass().getResource("/" + src).toString();
		String destfile = "";
		try {
			String destPath = "";
			destPath = FileUtils.URLToString(FileUtils.class.getResource("/"));
			File destPathFile = new File(destPath).getParentFile();
			destPath = destPathFile.getPath();
			destPath += File.separator + "temp" + File.separator;
			destPathFile = new File(destPath);
			if (!destPathFile.exists() || !destPathFile.isDirectory()) {
				destPathFile.mkdirs();
			}
			int index_file = Math.max(path.indexOf("file:/"),
					path.indexOf("file:\\"));
			int index_jarfile = Math.max(path.indexOf("jar:file:/"),
					path.indexOf("jar:file:\\"));
			index_file = Math.max(index_file, index_jarfile);
			int index_jar = Math.max(path.indexOf("jar!/"),
					path.indexOf("jar!\\"));
			if (index_file != -1) {
				if (index_jar != -1) {
					path = FileUtils.unzipFile(src, destPath, true);
				} else {
					path = FileUtils.URLToString(this.getClass().getResource(
							"/" + src));
				}
			} else {
				path = FileUtils.URLToString(this.getClass().getResource(
						"/" + src));
			}
			File jadFile = jad == null ? null : new File(jad);
			if (jadFile == null || !jadFile.exists() || !jadFile.isFile()) {
				jad = FileUtils.unzipFile("exe/jad.exe", destPath, true);
			}
			String command = jad + " -o -d" + destPath + " -sjava " + path;
			Process pro = Runtime.getRuntime().exec(command);
			// BufferedReader bufferedReader = new BufferedReader(
			// new InputStreamReader(pro.getInputStream()));
			BufferedReader buffered1Reader = new BufferedReader(
					new InputStreamReader(pro.getErrorStream()));
			log.info(command);
			String line = "";
			while ((line = buffered1Reader.readLine()) != null) {
				log.info(line);
				if (line != null && line.indexOf("Generating ") != -1) {
					destfile = line
							.substring(line.lastIndexOf("Generating ") + 11);
				}
				// pro.waitFor();
			}
			return destfile;
		} catch (Exception e) {
			log.error(e);
		}
		return "";
	}

}
